《汇编语言》(第四版) 实验 5 您所在的位置:网站首页 5 实验四 《汇编语言》(第四版) 实验 5

《汇编语言》(第四版) 实验 5

2024-05-18 19:28| 来源: 网络整理| 查看: 265

《汇编语言(第四版)》 . 王爽著 . 清华大学出版社 . 2019

¶实验 5 编写、调试具有多个段的程序

实现功能:利用栈,将程序中定义的数据逆序存放

在代码段中使用数据和栈

123456789101112131415161718192021222324252627282930313233assume cs:codesgcodesg segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;用 dw 定义 16 个字型数据,在程序加载后,将取得 16 个字的 ;内存空间,存放这 16 个数据。在后面的程序中将这段 ;空间当作栈来使用start: mov ax,cs mov ss,ax mov sp,30h ;将设置栈顶 ss:sp 指向 cs:30 mov bx,0 mov cx,8 s: push cs:[bx] add bx,2 loop s ;以上将代码段 0~15 单元中的 8 个字型数据依次入栈 mov bx,0 mov cx,8 s0: pop cs:[bx] add bx,2 loop s0 ;以上依次出栈 8 个字型数据到代码段 0~15 单元中 mov ax,4c00h int 21hcodesg endsend start ;指明程序的入口在 start 处

我们用 dw 在程序中写入了 16 个字型数据,即开辟了 32 个字节的内存空间(可以通过定义数据来取得一定容量的内存空间),在之后的程序中,我们设置 ss:sp 指向 cs:30,把这段内存空间(cs:10 ~ cs:2F)当作栈空间,注意 ss:sp 指向的是栈底,入栈时,栈顶从高地址向低地址方向增长

我们知道,在单任务系统中,可执行文件中的程序执行过程如下:

由其他的程序(Debug、command 或其他程序)将可执行文件中的程序加载入内存 设置 CS:IP 指向程序的第一条要执行的指令(即程序的入口),从而使程序得以运行 程序运行结束后,返回到加载者

我们在程序中用伪指令 end 指明程序的入口在何处,end start 即说明程序的入口在标号 start 处,通过这种方式使得 CS:IP 能够正确地指向程序的入口

在 8086 模式下,一个段的容量不能大于 64 KB,再者,将所有的数据、栈和代码都放在同一个段中使得程序显得混乱,考虑用多个段来存放数据、代码和栈

实现功能:利用栈,将程序中定义的数据逆序存放

将数据、代码、栈放入不同的段

123456789101112131415161718192021222324252627282930313233343536373839404142assume cs:code,ds:data,ss:stackdata segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdata endsstack segment dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0stack endscode segmentstart: mov ax,stack mov ss,ax mov sp,20h ;设置栈顶 ss:sp 指向 stack:20 mov ax,data mov ds,ax ;ds 指向 data 段 mov bx,0 ;ds:bx 指向 data 段中的第一个单元 mov cx,8 s: push [bx] add bx,2 loop s ;以上将 data 段中的 0~15 单元中的 8 个字型数据依次入栈 mov bx,0 mov cx,8 s0: pop [bx] add bx,2 loop s0 ;以上依次出栈 8 个字型数据到 data 段的 0~15 单元中 mov 4c00h int 21hcode endsend start

在一个段中,数据的段地址可由段名代表,程序中对段名的引用将被编译器处理为一个表示段地址的数值,因此在编写程序时不能将其直接送入段寄存器,数据的偏移地址取决于它在段中的位置

注意,伪指令 assume 并不能使 CPU 将 cs 指向 code、ds 指向 data、ss 指向 stack,CPU 到底如何处理我们定义的段中的内容,是当作指令执行,当作数据访问,还是当作栈空间,完全是由程序中具体的汇编指令和其对 CS:IP、SS:SP、DS 等寄存器的设置来决定的

¶实验任务(1)

将下面的程序编译、连接,用 Debug 加载、跟踪,然后回答问题

123456789101112131415161718192021222324252627282930assume cs:code, ds:data,ss:stackdata segment dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdata endsstack segment dw 0,0,0,0,0,0,0,0stack endscode segmentstart: mov ax,stack mov ss,ax mov sp,16 mov ax,data mov ds,ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21hcode endsend start 用 Debug 跟踪程序运行 程序将 data 段的数据入栈再出栈,在顺序上也对应,因此不会改变 data 段数据的值

CPU 执行程序,程序返回前,data 段中的数据为多少? CPU 执行程序,程序返回前,cs = ____ ss = ____ ds = ____。 设程序加载后,code 段的段地址为 X, 则 data 段的段地址为 ____ ,stack 段的段地址为 ____。

data 段中的数据未改变 cs = 076EH, ss = 076DH, ds = 076CH code 段的段地址为 X,则 data 段的段地址为 X-2, stack 段的段地址为 X-1

¶实验任务(2)

将下面的程序编译、连接,用 Debug 加载、跟踪,然后回答问题

123456789101112131415161718192021222324252627282930assume cs:code,ds:data,ss:stackdata segment dw 0123H,0456Hdata endsstack segment dw 0,0stack endscode segmentstart: mov ax,stack mov ss,ax mov sp,16 mov ax,data mov ds,ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21hcode endsend start 用 Debug 跟踪程序运行

CPU 执行程序,程序返回前,data 段中的数据为多少? CPU 执行程序,程序返回前,cs = ____ ss = ____ ds = ____。 设程序加载后,code 段的段地址为 X, 则 data 段的段地址为 ____ ,stack 段的段地址为 ____。 对于如下定义的段:

123name segment...name ends

如果段中的数据占 N 个字节,则程序加载后,该段实际占有的空间为 ____。

data 段中的数据未改变 cs = 076EH, ss = 076DH, ds = 076CH code 段的段地址为 X,则 data 段的段地址为 X-2, stack 段的段地址为 X-1

修改程序,改变数据与栈的长度

用 Debug 跟踪修改后的程序的运行,观察到 data 段的起始地址为 076C:0,stack 段的起始地址为 076E:0,code 段的起始地址即程序第一条指令的起始地址为 0770:0,发现虽然 data 段中只存放了 24 个字节、stack 段也只开了 20 个字节作为栈空间,但实际上,两个段都占有 32 个字节的空间

可以得出,实际占有空间为 $⌈\dfrac{N}{16}⌉ · 16$ ( ⌈…⌉ 为向上取整 )

¶实验任务(3)

将下面的程序编译、连接,用 Debug 加载、跟踪,然后回答问题

123456789101112131415161718192021222324252627282930assume cs:code,ds:data,ss:stackcode segmentstart: mov ax,stack mov ss,ax mov sp,16 mov ax,data mov ds,ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21hcode endsdata segment dw 0123H,0456Hdata endsstack segment dw 0,0stack endsend start 用 Debug 跟踪程序运行

CPU 执行程序,程序返回前,data 段中的数据为多少? CPU 执行程序,程序返回前,cs = ____ ss = ____ ds = ____。 设程序加载后,code 段的段地址为 X, 则 data 段的段地址为 ____ ,stack 段的段地址为 ____。

data 段中的数据未改变 cs = 076CH, ss = 0770H, ds = 076FH code 段的段地址为 X,则 data 段的段地址为 X+3, stack 段的段地址为 X+4

¶实验任务(4)

如果将(1) (2) (3)中的最后一条伪指令 end start 改为 end (也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。

(3) 仍可以正确执行 end start 改为 end 后,cs:ip 指向程序的首地址,只有 (3) 中的程序加载后 cs:ip 指向的是代码段

¶实验任务(5)

程序如下,编写 code 段的代码,将 a 段和 b 段中的数据依次相加,将结果存到 c 段中。

12345678910111213141516171819202122assume cs:codea segment db 1,2,3,4,5,6,7,8a endsb segment db 1,2,3,4,5,6,7,8b endsc segment db 0,0,0,0,0,0,0,0c endscode segmentstart: ?code endsend start

完整程序如下

12345678910111213141516171819202122232425262728293031323334assume cs:codea segment db 1,2,3,4,5,6,7,8a endsb segment db 1,2,3,4,5,6,7,8b endsc segment db 0,0,0,0,0,0,0,0c endscode segmentstart: mov ax,a mov ds,ax mov bx,0 mov cx,8 s: mov al,ds:[bx] add al,ds:[bx+16] mov ds:[bx+32],al inc bx loop s mov ax,4c00h int 21hcode endsend start

在编写程序时,我们通过前面的实验知道了如何推算一个段具体占有多少内存空间,那么当我们知道 a 段的起始地址为 a:0 时,我们就可以推出 b 段的起始地址为 a:0+16,c 段的起始地址为 a:0+32,从而使得在我们的程序中只需要用寄存器取一个段地址即可

注意,dw 的含义是定义字型数据,dw 即 define word,字型数据可以直接放入寄存器中去,因为数据寄存器的大小也是一个字的大小,而 db 的含义是定义字节型数据,db 即 define byte,字节型数据应该使用数据寄存器的高 8 位或是低 8 位进行存放

用 Debug 跟踪程序运行 ¶实验任务(6)

程序如下,编写 code 段的代码,用 push 指令将 a 段中的前 8 个字型数据,逆序存储到 b 段中。

123456789101112131415161718assume cs:codea segment dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffha endsb segment dw 0,0,0,0,0,0,0,0b endscode segmentstart: ?code endsend start

完整程序如下

123456789101112131415161718192021222324252627282930313233assume cs:codea segment dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffha endsb segment dw 0,0,0,0,0,0,0,0b endscode segmentstart: mov ax,a mov ds,ax mov ax,b mov ss,ax mov sp,16 mov bx,0 ;sub bx,bx mov cx,8 s: push ds:[bx] add bx,2 loop s mov ax,4c00h int 21h code endsend start

将 b 段视为栈空间,将 a 段中的前 8 个字型数据在循环中顺序压入栈中即可

用 Debug 跟踪程序运行 ¶汇编语言实验合集

汇编语言实验合集

实验 1 查看 CPU 和内存,用机器指令和汇编指令编程 实验 2 用机器指令和汇编指令编程 实验 3 编程、编译、连接、跟踪 实验 4 [bx] 和 loop 的使用 实验 5 编写、调试具有多个段的程序 实验 6 实践课程中的程序 实验 7 寻址方式在结构化数据访问中的应用 实验 8 分析一个奇怪的程序 实验 9 根据材料编程 实验 10 编写子程序 课程设计 1 实验 11 编写子程序 实验 12 编写 0 号中断的处理程序 实验 13 编写、应用中断例程 实验 14 访问 CMOS RAM 实验 15 安装新的 int9 中断例程 实验 16 编写包含多个功能子程序的中断例程 实验 17 编写包含多个功能子程序的中断例程 课程设计 2



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有